#include "stdafx.h"
#include <MyViews/Workbench.h>
#include <MyViews/Tool.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

Workbench::Workbench()
{
	m_pTool = 0;
	m_pActiveTool = 0;
	m_pAltTool = 0;
	m_Inside = false;
}

Workbench::~Workbench()
{
}

Tool * Workbench::GetTool() const
{
	return m_pAltTool != 0 ? m_pAltTool : m_pActiveTool;
}

void Workbench::SetActiveTool(Tool * pTool)
{
	if (pTool != m_pActiveTool)
	{
		SetAltTool(0);
		m_pActiveTool = pTool;
		UpdateCursor();
		HandleActiveToolChange();
	}
}
			  
void Workbench::SetAltTool(Tool * pTool)
{
	if (pTool != m_pAltTool) {
		Tool * pPrev = GetCurrentTool();
		m_pAltTool = pTool;
		Tool * pCur = GetCurrentTool();
		if (pPrev != 0)
			pPrev->Hide();
		if (pCur != 0)
			pCur->Show();
		UpdateCursor();
		HandleAltToolChange();
	}
}

void Workbench::SetManipulator(std::auto_ptr<Manipulator> pManip)
{
	if (m_pManip.get() != pManip.get()) {
		m_pManip = pManip;
		UpdateCursor();
	}
}

Tool * Workbench::GetCurrentTool() const
{
	Tool * pTool = GetTool();
	if (pTool != m_pTool) {
		Workbench & me = const_cast<Workbench &>(* this);
		if (me.m_pTool != 0)
			me.m_pTool->Deactivate();
		me.m_pTool = pTool;
		if (me.m_pTool != 0)
			me.m_pTool->Activate();
		me.m_pTool = pTool;
	}
	return pTool;
}


void Workbench::UpdateCursor()
{
	if (m_hWnd != 0 && m_Inside)
		SendMessage(WM_SETCURSOR, WPARAM(m_hWnd), HTCLIENT);
}

/////////////////////////////////////////////////////////////////////////////
// Workbench message handlers

BOOL Workbench::OnCmdMsg(UINT nID, int nCode, void* pExtra, AFX_CMDHANDLERINFO* pHandlerInfo) 
{
	Tool * pTool = GetCurrentTool();
	if (pTool != 0 
		&& pTool->OnCmdMsg(nID, nCode, pExtra, pHandlerInfo))
		return TRUE;
	else	
		return BasicView::OnCmdMsg(nID, nCode, pExtra, pHandlerInfo);
}

void Workbench::OnActivateView(BOOL bActivate, CView * pActivateView, CView * pDeactiveView) 
{
	Tool * pTool = GetCurrentTool();
	if (pTool != 0)
		pTool->OnActivateView();
	BasicView::OnActivateView(bActivate, pActivateView, pDeactiveView);
}

void Workbench::HandleKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	Tool * pTool = GetCurrentTool();
	if (pTool != 0)
		pTool->OnKeyDown(nChar, nRepCnt, nFlags);
	BasicView::HandleKeyDown(nChar, nRepCnt, nFlags);
}

void Workbench::HandleKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	Tool * pTool = GetCurrentTool();
	if (pTool != 0)
		pTool->OnKeyUp(nChar, nRepCnt, nFlags);		
	BasicView::HandleKeyUp(nChar, nRepCnt, nFlags);
}

void Workbench::HandleSysKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	Tool * pTool = GetCurrentTool();
	if (pTool != 0)
		pTool->OnKeyDown(nChar, nRepCnt, nFlags);
	BasicView::HandleSysKeyDown(nChar, nRepCnt, nFlags);
}

void Workbench::HandleSysKeyUp(UINT nChar, UINT nRepCnt, UINT nFlags) 
{
	Tool * pTool = GetCurrentTool();
	if (pTool != 0)
		pTool->OnKeyUp(nChar, nRepCnt, nFlags);		
	BasicView::HandleSysKeyUp(nChar, nRepCnt, nFlags);
}


void Workbench::HandleLButtonDblClk(UINT nFlags, CPoint p) 
{
	Tool * pTool = GetCurrentTool();
	if (pTool != 0)
		pTool->OnLButtonDblClk(nFlags, p);
	BasicView::HandleLButtonDblClk(nFlags, p);
}

void Workbench::HandleLButtonDown(UINT nFlags, CPoint p) 
{
	Tool * pTool = GetCurrentTool();
	if (pTool != 0)
		pTool->OnLButtonDown(nFlags, p);
	BasicView::HandleLButtonDown(nFlags, p);
}

void Workbench::HandleLButtonUp(UINT nFlags, CPoint p) 
{
	if (m_pManip.get()) {
		m_pManip->Apply(nFlags, p);
		m_pManip.reset();
		return;
	}
	Tool * pTool = GetCurrentTool();
	if (pTool != 0)
		pTool->OnLButtonUp(nFlags, p);
	BasicView::HandleLButtonUp(nFlags, p);
}

void Workbench::HandleMouseMove(UINT nFlags, CPoint p) 
{
	if (!m_Inside) 
	{
		m_Inside = true;
//		GetParentFrame()->SetWindowText("Inside = true");
		Tool * pTool = GetCurrentTool();
		if (pTool != 0)
			pTool->OnMouseEnter(nFlags, p);
		
		TRACKMOUSEEVENT tme;
		tme.cbSize = sizeof(tme);
		tme.dwFlags = TME_LEAVE;
		tme.hwndTrack = m_hWnd;
		tme.dwHoverTime = 0;		
		VERIFY(_TrackMouseEvent(&tme));
	}

	if (m_pManip.get()) {
		m_pManip->Manipulate(nFlags, p);
		return;
	}

	Tool * pTool = GetCurrentTool();
	if (pTool != 0)
		pTool->OnMouseMove(nFlags, p);
	BasicView::HandleMouseMove(nFlags, p);
}

void Workbench::HandleRButtonDblClk(UINT nFlags, CPoint p) 
{
	Tool * pTool = GetCurrentTool();
	if (pTool != 0)
		pTool->OnRButtonDblClk(nFlags, p);
	BasicView::HandleRButtonDblClk(nFlags, p);
}

void Workbench::HandleRButtonDown(UINT nFlags, CPoint p) 
{
	Tool * pTool = GetCurrentTool();
	if (pTool != 0)
		pTool->OnRButtonDown(nFlags, p);
	BasicView::HandleRButtonDown(nFlags, p);
}

void Workbench::HandleRButtonUp(UINT nFlags, CPoint p) 
{
	Tool * pTool = GetCurrentTool();
	if (pTool != 0)
		pTool->OnRButtonUp(nFlags, p);
	BasicView::HandleRButtonUp(nFlags, p);
}

void Workbench::HandleSize(UINT nType, int cx, int cy)
{
	Tool * pTool = GetCurrentTool();
	if (pTool != 0)
		pTool->OnResize(nType, cx, cy);
	BasicView::HandleSize(nType, cx, cy);
}

BOOL Workbench::HandleSetCursor(CWnd* pWnd, UINT nHitTest, UINT message) 
{
	if (nHitTest == HTCLIENT && m_pManip.get() != 0) {
		CPoint p;
		GetCursorPos(&p);
		ScreenToClient(&p);
		if (m_pManip->OnSetCursor(p))
			return TRUE;
	}
	Tool * pTool = GetCurrentTool();
	if (nHitTest == HTCLIENT 
		&& pTool != 0 
		&& pTool->OnSetCursor(pWnd, nHitTest, message))
		return TRUE;
	else
		return BasicView::HandleSetCursor(pWnd, nHitTest, message);
}

void Workbench::HandleSetFocus(CWnd* pOldWnd) 
{
	Tool * pTool = GetCurrentTool();
	BasicView::HandleSetFocus(pOldWnd);
	if (pTool != 0)
		pTool->OnSetFocus();
}

void Workbench::HandleKillFocus(CWnd* pNewWnd) 
{
	Tool * pTool = GetCurrentTool();
	BasicView::HandleKillFocus(pNewWnd);
	if (pTool != 0)
		pTool->OnKillFocus();
}

void Workbench::HandleMouseLeave()
{
//	GetParentFrame()->SetWindowText("Inside = false");

	Tool * pTool = GetCurrentTool();
	if (pTool != 0)
		pTool->OnMouseLeave();

	m_Inside = false;
}












